<template>
	<view class="number-box">
		<view class="number-box-reduce" @click="clickHandler('minus')">
			<view class="number-box-reduce-text" hover-class="clickable">-</view>
		</view>
		<input type="digit" v-model="currentValue" @input="onInput" @blur="onBlur"/>
		<view class="number-box-add" @click="clickHandler('plus')">
			<view class="number-box-add-text" hover-class="clickable">+</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				currentValue: 0,
				step: 1
			}
		},
		props: {
			value: {
				type: [String, Number],
				default: 0
			},
			max: {
				type: [String, Number],
				default: Number.MAX_SAFE_INTEGER
			},
			min: {
				type: [String, Number],
				default: -Number.MAX_SAFE_INTEGER
			},
		},
		watch: {
			value(val) {
				this.currentValue = val;
			}
		},
		created() {
			this.currentValue = this.value*1;
		},
		methods: {
			// 点击加减按钮
			clickHandler(type) {
				this.type = type
				this.onChange()
			},
			onChange() {
				const {
					type
				} = this
				const diff = type === 'minus' ? -this.step : +this.step;
				let value = this.format(+this.currentValue, diff)
				value = this.check(value)
				this.emitChange(value)
			},
			// 对值扩大后进行四舍五入，再除以扩大因子，避免出现浮点数操作的精度问题
			format(num1, num2) {
				const cardinal = Math.pow(10, 10);
				return Math.round((num1 + num2) * cardinal) / cardinal
			},
			// 限制范围
			check(value) {
				value = Math.max(Math.min(this.max, value), this.min)
				return value
			},
			onInput(e) {
				const {
					value = ''
				} = e.detail || {}
				// 为空返回
				if (value === '') return
				this.emitChange(value)
			},
			// 异步变更值
			emitChange(value) {
				this.$nextTick(() => {
					this.$emit('input', value)
					this.currentValue = value
					this.$forceUpdate()
				})
			},
			// 输入框失去焦点
			onBlur(event) {
				// 对输入值进行格式化
				let value = this.check(event.detail.value)
				this.emitChange(value)
				// 发出blur事件
				this.$emit(
					'blur',{
						...event.detail
					}
				)
			},
		}
	}
</script>

<style scoped lang="scss">
	.number-box {
		display: flex;
		align-items: center;
		height: 60rpx;
		
		&-reduce,&-add {
			width: 80rpx;
			height: 100%;
			background-color: #eee;
			border-radius: 5rpx;
			
			&-text {
				height: 100%;
				font-size: 60rpx;
				display: flex;
				align-items: center;
				justify-content: center;
			}
		}
		
		input {
			width: 140rpx;
			height: 100%;
			background-color: #eee;
			margin: 0 5rpx;
			text-align: center;
			color: #000;
			font-size: 28rpx;
			border-radius: 5rpx;
		}
	}
</style>
